﻿using Newtonsoft.Json;
using System;
using System.Diagnostics;
using YamlDotNet.Serialization;
using static System.Collections.Specialized.BitVector32;

namespace Wargame_V3_1
{
    public class GameEvolver
    {
        private Dictionary<string, Dictionary<string, string>> actionModels = new Dictionary<string, Dictionary<string, string>>();  // 从ActionModels中读入的action模型
        private Dictionary<string, Dictionary<string, string>> interactModels = new Dictionary<string, Dictionary<string, string>>();  // 从InteractModels中读入的interact模型
        private Dictionary<string, Dictionary<string, string>> judgeInfoModels = new Dictionary<string, Dictionary<string, string>>();
        private Dictionary<string, OperatorModel> operatorModels = new Dictionary<string, OperatorModel>();
        private Dictionary<string, TargetModel> targetModels = new Dictionary<string, TargetModel>();

        public List<Operator> operators = new List<Operator>();  // 保存所有的算子对象
        public List<Target> targets = new List<Target>();  // 保存所有的目标对象
        private List<Action> actions = new List<Action>();  // 临时记录所有动作信息
        private List<Interact> interacts = new List<Interact>();  // 临时记录所有交互信息
        private List<JudgeInfo> judgeInfoes = new List<JudgeInfo>();  // 临时记录所有裁决信息


        public Map map;
        public ShootJudge shootJudge;  // 射击裁决表（射击裁决使用）
        private Observation observation = new Observation();  // 当前的全局态势
        private Dictionary<string, dynamic> fullObservation;  // 所有态势，包括全局态势、红方态势、蓝方态势等

        // TODO 2024-4-8 推演引擎中不再保存复盘数据，后面在外部程序中根据接收到的observation保存复盘，以节省GameEnvolver的计算量
        private List<Dictionary<string, object>> replayData = new List<Dictionary<string, object>>();  // 复盘数据

        List<string> colors = new List<string>();

        /// <summary>
        /// 构造方法：输入配置文件config.yml的全路径，根据config.yml文件中的配置内容完成推演引擎初始化
        /// </summary>
        /// <param name="configPath">配置文件路径，例如"\wargame-v3_0\config\config.yml"或者config.yml所在文件夹路径</param>
        public GameEvolver(string configPath)
        {
            // === 找到并读取config.yml文件 ===
            string extension = Path.GetExtension(configPath);
            string configFile = "";
            if (extension == ".yml" || extension == ".yaml")
            {
                configFile = configPath;
            }
            else if (extension == "")
            {
                string[] files = Directory.GetFiles(configPath);
                bool findConfig = false;
                foreach (string file in files)
                {
                    if (Path.GetFileName(file) == "config.yml")
                    {
                        configFile = file;
                        findConfig = true;
                        break;
                    }
                }
                if (!findConfig)
                {
                    throw new Exception($"输入的配置文件路径{configPath}中没有config.yml配置文件！");
                }
            }
            else
            {
                throw new Exception($"输入的配置文件路径{configPath}有误，应为config.yml所有文件夹路径或者后缀名为.yaml/.yml的文件全路径。");
            }
            // 读取config.yml文件
            Deserializer deserializer = new Deserializer();
            Dictionary<string, object> configContents;  // 从yml文件中读取的内容
            using (var reader = new StreamReader(configFile))
            {
                configContents = deserializer.Deserialize<Dictionary<string, object>>(reader);
            }

            // === 生成日志目录 ===
            string logDir = configContents["log_dir"].ToString();
            if (!Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }
            string logName = DateTime.Now.ToString("yyyyMMddHHmm") + ".log";
            Trace.Listeners.Add(new TextWriterTraceListener(logDir + "\\" + logName));
            Trace.AutoFlush = true;

            // === 读入想定文件 ===
            string configDir = configContents["config_dir"].ToString();
            string scenarioFile = configContents["Scenario"].ToString();
            Dictionary<string, object> scenarioData;
            List<object> operatorsData;
            List<object> targetsData;
            using (StreamReader sr = new StreamReader(configDir + "\\" + scenarioFile))
            {
                string dataString = sr.ReadToEnd();
                scenarioData = JsonConvert.DeserializeObject<Dictionary<string, object>>(dataString);
                try
                {
                    operatorsData = JsonConvert.DeserializeObject<List<object>>(scenarioData["Operators"].ToString());
                }
                catch (Exception ex)
                {
                    Trace.TraceError("想定文件中缺少算子数据");
                    throw new Exception("想定文件中缺少算子数据：" + ex);
                }
                try
                {
                    targetsData = JsonConvert.DeserializeObject<List<object>>(scenarioData["Targets"].ToString());
                }
                catch (Exception ex)
                {
                    Trace.TraceError("想定文件中缺少目标数据");
                    throw new Exception("想定文件中缺少目标数据：" + ex);
                }
                /*try
                {
                    cities = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(scenarioData["cities"].ToString());
                }
                catch (Exception ex)
                {
                    Trace.TraceError("想定文件中缺少夺控点数据");
                    throw new Exception("想定文件中缺少夺控点数据：" + ex);
                }

                try
                {
                    time = JsonConvert.DeserializeObject<Dictionary<string, object>>(scenarioData["time"].ToString());
                }
                catch (Exception ex)
                {
                    Trace.TraceError("想定文件中缺少时间数据");
                    throw new Exception("想定文件中缺少时间数据：" + ex);
                }*/
            }
            // === 读入算子模型 ===
            Dictionary<object, object> oprPaths = (Dictionary<object, object>)configContents["Operators"];
            foreach (KeyValuePair<object, object> oprItem in oprPaths)
            {
                string oprName = oprItem.Key.ToString();
                string oprPath = oprItem.Value.ToString();
                OperatorModel om = new OperatorModel(oprName, configDir + "\\" + oprPath);
                if (om.IsValid())
                {
                    operatorModels.Add(om.Name, om);
                }
            }
            // === 根据算子模型和想定中的算子数据，实例化算子对象 ===
            foreach (object oprData in operatorsData)//遍历想定中的算子数据
            {
                Dictionary<string, object> oprDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(oprData.ToString());//oprDict是算子，即string类型的属性和其对应的属性值
                if (oprDict.ContainsKey("SubType"))
                {
                    string subType = oprDict["SubType"].ToString();// 取得细分类型属性
                    if (operatorModels.ContainsKey(subType))// 是否有此细分类型的算子模型
                    {
                        operators.Add(operatorModels[subType].CreateOprInstance(oprDict));// 用想定中的算子属性传入模型，来构造算子接口类型的数据
                    }
                }
            }
            // === 读入目标模型 ===
            Dictionary<object, object> tarPaths = (Dictionary<object, object>)configContents["Targets"];
            foreach (KeyValuePair<object, object> tarItem in tarPaths)
            {
                string tarName = tarItem.Key.ToString();
                string tarPath = tarItem.Value.ToString();
                TargetModel tm = new TargetModel(tarName, configDir + "\\" + tarPath);
                if (tm.IsValid())
                {
                    targetModels.Add(tm.Name, tm);
                }
            }
            // === 根据目标模型和想定中的目标数据，实例化目标对象 ===
            foreach (object tarData in targetsData)//遍历想定中的算子数据
            {
                Dictionary<string, object> tarDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(tarData.ToString());
                if (tarDict.ContainsKey("Type"))
                {
                    string tarType = tarDict["Type"].ToString();// 取得目标类型属性
                    if (targetModels.ContainsKey(tarType))// 是否有此类型的目标模型
                    {
                        targets.Add(targetModels[tarType].CreateOprInstance(tarDict));
                    }
                }
            }
            // === 读入action模型 ===
            string actionFile = configContents["Actions"].ToString();
            using (StreamReader sr = new StreamReader(configDir + "\\" + actionFile))
            {
                string dataString = sr.ReadToEnd();
                actionModels = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(dataString);
            }
            // === 读入interact模型 ===
            string interactFile = configContents["Interact"].ToString();
            using (StreamReader sr = new StreamReader(configPath + "\\" + interactFile))
            {
                string dataString = sr.ReadToEnd();
                interactModels = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(dataString);
            }
            // === 读入judgeInfo模型 ===
            string judgeInfoFile = configContents["JudgeInfo"].ToString();
            using (StreamReader sr = new StreamReader(configPath + "\\" + judgeInfoFile))
            {
                string dataString = sr.ReadToEnd();
                judgeInfoModels = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(dataString);
            }
            // === 初始化地图 ===
            string mapDir = configContents["Map"].ToString();
            map = new Map(configDir + "\\" + mapDir);
            // === 初始化设计裁决表 ===
            shootJudge = new ShootJudge(configPath + @"\shoot_judge_tables");
            // === 读入其它模型 ===
            // TODO
            /* TODO 放入Observation类中，调用Update时更新这些信息
             * // === 保存最大分数 ===
            foreach (dynamic opr in operators)
            {
                if (opr.Color == "Red") red_remain_max += (opr.Value * opr.MaxBlood);// 分值×最大血量
                else if (opr.Color == "Blue") blue_remain_max += (opr.Value * opr.MaxBlood);
            }*/
            // === 确定对抗方 ===
            ((List<object>)configContents["agent_colors"]).ForEach(color => colors.Add(color.ToString()));
            colors.Add("All");
            // === 初始化态势 ===
            // 1. 读入态势模型，定义态势对象
            string obModelPath = configDir + "\\" + configContents["Observation"].ToString();
            observation.Init(obModelPath);
            // 2. 根据想定数据更新态势对象的属性
            observation.SetAttri("Actions", actions);
            observation.SetAttri("JudgeInfoes", judgeInfoes);
            observation.SetAttri("Operators", operators);
            observation.SetAttri("Targets", targets);
            foreach (KeyValuePair<string, object> item in scenarioData)
            {
                if (new string[] { "Actions", "JudgeInfoes", "Operators", "Targets" }.Contains(item.Key))
                {
                    continue;
                }
                observation.SetAttri(item.Key, item.Value);
            }
        }

        /// <summary>
        /// 用于外部计时器的调用，推进兵棋态势演进
        /// </summary>
        /// <param name="actionsString">由智能体或人工提供的动作字符串，格式为"[{}, {}, ...]"</param>
        public string Step(string actionsString, double time)
        {
            // 把一些临时信息置空
            actions = new List<Action>();
            interacts = new List<Interact>();
            judgeInfoes = new List<JudgeInfo>();

            // 对actions进行清理，去除重复的和不再validActions中的。
            List<Dictionary<string, string>> actionListString = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(actionsString);

            // 此处只做去重
            actionListString = ValidateAction(actionListString);

            // === 把actions字符串转换成List<Action>的格式 ===
            try
            {
                foreach (Dictionary<string, string> actionDict in actionListString)
                {
                    actions.Add(new Action(actionModels, actionDict));
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError("输入的actions的格式不正确：" + ex.Message);
            }
            // === 遍历各个action，调用对应算子的Callout方法，更新算子状态，输出interact（不产生交互的，输出null） ===
            List<Dictionary<string, object>> interactDicts = new List<Dictionary<string, object>>();
            foreach (dynamic action in actions)
            {
                Operator opr = GetOprByID(action.ObjID);
                Dictionary<string, dynamic> param = new Dictionary<string, dynamic>
                {
                    {"action",action},{"map",map},{"oprs",operators},{"targets",targets},{"shootJudge", shootJudge},{"curStep", time}
                };
                Dictionary<string, object> interactDict = opr.InvokeMethod("CalloutAction", param);
                if (interactDict != null)
                {
                    interactDicts.Add(interactDict);
                }
            }
            // === 遍历所有interact，调用对应算子的Callout方法，更新算子状态 ===
            // 2024-4-6, 增加了交互对目标（夺控点）的影响，交互调用方法的输出是裁决信息judgeInfo
            List<Dictionary<string, object>> judgeInfoDicts = new List<Dictionary<string, object>>();
            if (interactDicts.Count > 0)
            {
                foreach (Dictionary<string, object> interactDict in interactDicts)
                {
                    dynamic interact = new Interact(interactModels, interactDict);
                    interacts.Add(interact);
                    if (interact.ObjID != null)  // 该交互的作用方是算子
                    {
                        Operator opr = GetOprByID(interact.ObjID);
                        Dictionary<string, dynamic> param = new Dictionary<string, dynamic>
                        {
                            {"interact",interact},{"map",map},{"shootJudge", shootJudge},{"curStep", time}
                        };
                        Dictionary<string, object> judgeInfoDict = opr.InvokeMethod("CalloutInteract", param);
                        if (judgeInfoDict != null)
                        {
                            judgeInfoDicts.Add(judgeInfoDict);
                        }
                    }
                    else if (interact.TarID != null)  // 该交互的作用方是目标，例如夺控点
                    {
                        Target tar = GetTarByID(interact.TarID);
                        Dictionary<string, dynamic> param = new Dictionary<string, dynamic>
                        {
                            {"interact",interact},{"curStep", time}
                        };
                        Dictionary<string, object> judgeInfoDict = tar.InvokeMethod("CalloutInteract", param);
                        if (judgeInfoDict != null)
                        {
                            judgeInfoDicts.Add(judgeInfoDict);
                        }
                    }
                    else
                    {
                        Trace.TraceWarning($"交互{interact}的格式不符合标准。");
                    }
                }
            }

            // === 对算子状态进行同步 ===
            foreach (Operator opr in operators)
            {
                Dictionary<string, dynamic> param = new Dictionary<string, dynamic>
                {
                    {"obsv",observation},{"map",map},{"oprs",operators},{"curStep",time}
                };
                opr.InvokeMethod("SynchronizeByStep", param);
            }

            // === 更新裁决信息 ===
            if (judgeInfoDicts.Count > 0)
            {
                foreach (Dictionary<string, object> judgeInfoDict in judgeInfoDicts)
                {
                    judgeInfoes.Add(new JudgeInfo(judgeInfoModels, judgeInfoDict));
                }
            }

            // 删除血量为0的算子
            for (int i = 0; i < operators.Count;)
            {
                Operator opr = operators[i];
                if (opr.GetAttri("Blood") <= 0) operators.RemoveAt(i);
                else i++;
            }

            Dictionary<int, List<string>> validActions = new Dictionary<int, List<string>>();
            foreach (Operator opr in operators)
            {
                Dictionary<string, dynamic> param = new Dictionary<string, dynamic>
                {
                    {"map",map},{"oprs",operators},{"targets",targets},{"shootJudge", shootJudge}
                };
                validActions[opr.GetAttri("ObjID")] = opr.InvokeMethod("UpdateValidActions", param);
            }

            observation.InvokeMethod("Update", new Dictionary<string, dynamic> { { "oprs", operators }, { "acitons", actions }, { "targets", targets }, { "judgeInfoes", judgeInfoes }, { "curStep", time }, { "validActions", validActions } });

            fullObservation = observation.InvokeMethod("Distribute", new Dictionary<string, dynamic> { { "colors", colors } });

            return JsonConvert.SerializeObject(fullObservation);
            /*
             * //time
            time["cur_step"] = stopwatch.Elapsed.TotalSeconds;

            //scores
            scores = UpdateScores(operators, cities);

            //fullObservation
            Dictionary<string, object> observation = new Dictionary<string, object>
            {
                { "actions", actions },
                { "cities", cities },
                { "judge_info", judge_info },
                { "operators", operators },
                { "scores", scores },
                { "time", time },
                { "valid_actions", valid_actions }
            };
            fullObservation = PartitionObservation(observation);

            //replayData
            replayData.Add(fullObservation["All"]);
            if (double.Parse(time["cur_step"].ToString()) >= int.Parse(time["max_time"].ToString())) { GetReplayData(); }

            return JsonConvert.SerializeObject(observation);  // 改成态势信息的字符串*/
        }

        ///// <summary>
        ///// 把replayData转成字符串进行输出
        ///// </summary>
        ///// <returns></returns>
        //public string GetReplayData()
        //{
        //    string replayDataDir = Directory.GetCurrentDirectory() + "\\..\\..\\..\\Replay data\\";
        //    if (!Directory.Exists(replayDataDir))
        //    {
        //        Directory.CreateDirectory(replayDataDir);
        //    }
        //    //Formatting.Indented参数用于在生成的JSON字符串中添加缩进和换行符
        //    string json = JsonConvert.SerializeObject(replayData, Formatting.Indented);
        //    string fileName = "replay_" + DateTime.Now.ToString("yyyyMMddHHmm") + ".json";
        //    File.WriteAllText(replayDataDir + fileName, json);
        //    return null;
        //}
        ///// <summary>
        ///// 分配态势，形成fullObservation
        ///// </summary>
        ///// <param name="observation"></param>
        ///// <returns></returns>
        //private Dictionary<string, Dictionary<string, object>> PartitionObservation(Dictionary<string, object> observation)
        //{
        //    Dictionary<string, Dictionary<string, object>> fullObservation = new Dictionary<string, Dictionary<string, object>>
        //    {
        //        { "All", JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonConvert.SerializeObject(observation)) },// 深度拷贝一份
        //        { "Red", AssignObservation("Red", observation) },
        //        { "Blue", AssignObservation("Blue", observation) }
        //    };
        //    return fullObservation;
        //}
        //private Dictionary<string, object> AssignObservation(string color, Dictionary<string, object> observation)
        //{
        //    // 深度拷贝一份，用作下面的修改
        //    Dictionary<string, object> local_observation = JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonConvert.SerializeObject(observation));

        //    // 取出保存color方的动作
        //    List<Action> actions = new List<Action>();
        //    foreach (dynamic action in JsonConvert.DeserializeObject<List<Action>>(JsonConvert.SerializeObject(local_observation["actions"])))// object类型转List<DynamicAction>
        //    {
        //        dynamic opr = GetOprByID((int)action.ObjID);
        //        if (opr.Color == color) actions.Add(action);
        //    }

        //    // 更新color方的valid_actions
        //    Dictionary<string, Dictionary<string, List<Dictionary<string, object>>>> valid_actions = new Dictionary<string, Dictionary<string, List<Dictionary<string, object>>>>();
        //    foreach (var opr_actions in JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, List<Dictionary<string, object>>>>>(JsonConvert.SerializeObject(local_observation["valid_actions"])))// object类型转换
        //    {
        //        string obj_id = opr_actions.Key;
        //        Dictionary<string, List<Dictionary<string, object>>> individual_valid_actions = opr_actions.Value;
        //        dynamic opr = GetOprByID(int.Parse(obj_id));// 字符串转整数
        //        if (opr.Color == color) valid_actions.Add(obj_id, individual_valid_actions);
        //    }

        //    // 更新operators
        //    List<IOperator> operators = new List<IOperator>();
        //    List<IOperator> our_operators = new List<IOperator>();
        //    List<IOperator> enemies = new List<IOperator>();
        //    foreach (object oprData in (List<object>)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(local_observation["operators"]), typeof(List<object>)))
        //    {
        //        // object转为IOperator
        //        dynamic opr = null;
        //        Dictionary<string, object> oprDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(oprData.ToString());//oprDict是算子，即string类型的属性和其对应的属性值
        //        opr = operatorModels[oprDict["Subtype"].ToString()].CreateOprInstance(oprDict);// 用想定中的算子属性传入模型，来构造算子接口类型的数据

        //        if (opr.Color == color)
        //        {
        //            operators.Add(opr);
        //            our_operators.Add(opr);
        //        }
        //        else
        //        {
        //            enemies.Add(opr);
        //        }
        //    }
        //    for (int i = 0; i < enemies.Count; i++)
        //    {
        //        dynamic enemy = enemies[i];
        //        bool can_be_seen = false;
        //        foreach (dynamic opr in our_operators)
        //        {
        //            if (opr.SeeEnemyBopIDs == null) continue;
        //            if (opr.SeeEnemyBopIDs.Contains(enemy.ObjID))
        //            {
        //                can_be_seen = true;
        //                break;
        //            }
        //        }
        //        if (can_be_seen)  // 能被看见的情况，隐藏迷雾属性
        //        {
        //            // 避免算子取属性失败而触发中断
        //            try
        //            {
        //                foreach (var weapon in enemy.RemainBulletNums.Keys) { enemy.RemainBulletNums[weapon] = -1; }
        //            }
        //            catch (Exception ex) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的RemainBulletNums属性出错：" + ex); }
        //            try { enemy.MoveToStopRemainTime = -1; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的MoveToStopRemainTime属性出错：" + e); }
        //            try { enemy.CanToMove = false; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的CanToMove属性出错：" + e); }
        //            try { enemy.MovePath = new List<int>(); } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的MovePath属性出错：" + e); }
        //            try { enemy.TireAccumulateTime = -1; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的TireAccumulateTime属性出错：" + e); }
        //            try { enemy.KeepRemainTime = -1; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的KeepRemainTime属性出错：" + e); }
        //            try { enemy.Launcher = -1; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的Launcher属性出错：" + e); }
        //            try { enemy.LaunchIDs = new List<int>(); } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的LaunchIDs属性出错：" + e); }
        //            try { enemy.AliveRemainTime = -1; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的AliveRemainTime属性出错：" + e); }
        //            try { enemy.GetOnRemainTime = -1; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的GetOnRemainTime属性出错：" + e); }
        //            try { enemy.GetOffRemainTime = -1; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的GetOffRemainTime属性出错：" + e); }
        //            try { enemy.WeaponUnfoldTime = -1; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的WeaponUnfoldTime属性出错：" + e); }
        //            try { enemy.SeeEnemyBopIDs = -1; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的SeeEnemyBopIDs属性出错：" + e); }
        //            try { enemy.TargetState = ""; } catch (Exception e) { Trace.TraceError($"分配态势出错：修改敌方算子{enemy.ObjID}的TargetState属性出错：" + e); }
        //            operators.Add(enemy);
        //        }
        //    }

        //    // 更新CurObservation[color]
        //    local_observation["actions"] = actions;
        //    local_observation["valid_actions"] = valid_actions;
        //    local_observation["operators"] = operators;

        //    return local_observation;
        //}
        ///// <summary>
        ///// 根据算子的夺控裁决结果更新夺控点的属性
        ///// </summary>
        ///// <param name="operators"></param>
        ///// <param name="cities"></param>
        ///// <returns></returns>
        //private List<Dictionary<string, object>> UpDateCities(List<IOperator> operators, List<Dictionary<string, object>> cities)
        //{
        //    foreach (dynamic opr in operators)
        //    {
        //        try { if (opr.JudgeInfoes == null) continue; } catch { continue; }// 无裁决信息属性，或者无裁决信息

        //        foreach (var judgeInfo in opr.JudgeInfoes)
        //        {
        //            if (judgeInfo["type"] == "Occupy" && judgeInfo["is_success"])
        //            {
        //                foreach (var city in cities)
        //                {
        //                    if (city["coord"] == judgeInfo["coord"]) city["flag"] = judgeInfo["color"];
        //                }
        //            }
        //        }
        //    }
        //    return cities;
        //}
        ///// <summary>
        ///// 计算双方得分
        ///// </summary>
        ///// <param name="operators"></param>
        ///// <param name="cities"></param>
        ///// <returns></returns>
        //private Dictionary<string, int> UpdateScores(List<IOperator> operators, List<Dictionary<string, object>> cities)
        //{
        //    int blue_remain_max = this.blue_remain_max;// 取得蓝方最大可获得的分数
        //    int red_remain_max = this.red_remain_max;// 取得红方最大可获得的分数

        //    int blue_attack = 0;// 蓝方攻击得分
        //    int blue_occupy = 0;// 蓝方夺控分
        //    int blue_remain = 0;// 蓝方剩余得分
        //    //int blue_remain_max = blue_remain_max;// 蓝方最大剩余得分
        //    int blue_total = 0;// 蓝方总分
        //    int blue_win = 0;// 蓝方净胜分
        //    int red_attack = 0;// 红方战斗得分
        //    int red_occupy = 0;// 红方夺控分
        //    int red_remain = 0;// 红方剩余算子分
        //    //int red_remain_max = red_remain_max;// 红方最大剩余得分
        //    int red_total = 0;// 红方总分
        //    int red_win = 0;// 红方净胜分

        //    // ===计算当前所有的得分===
        //    // 算子分数
        //    foreach (dynamic opr in operators)// 遍历态势中剩下的算子
        //    {
        //        if (opr.Color == "Red")// 红方
        //        {
        //            red_remain += (opr.Value * opr.Blood);// 红方剩余算子的分值 乘 算子剩余血量
        //        }
        //        else if (opr.Color == "Blue")// 蓝方
        //        {
        //            blue_remain += (opr.Value * opr.Blood);// 蓝方剩余算子的分值 乘 算子剩余血量
        //        }
        //    }
        //    // 夺控点分数
        //    foreach (var city in cities)
        //    {
        //        if (city["flag"].ToString() == "Red")
        //        {
        //            red_occupy += int.Parse(city["value"].ToString());// 每个红方的夺控点的夺控点分数的和
        //        }
        //        else if (city["flag"].ToString() == "Blue")
        //        {
        //            blue_occupy += int.Parse(city["value"].ToString());// 每个蓝方的夺控点的夺控点分数的和
        //        }
        //    }
        //    blue_attack = red_remain_max - red_remain;// 蓝方攻击得分等于 红方最大剩余得分 减 红方剩余算子分
        //    red_attack = blue_remain_max - blue_remain;// 红方攻击得分等于 蓝方最大剩余得分 减 蓝方剩余算子分
        //    blue_total = blue_attack + blue_occupy;// 总得分等于攻击得分加夺控得分
        //    red_total = red_attack + red_occupy;
        //    blue_win = blue_total - red_total;// 净胜分等于双方总分的差
        //    red_win = -blue_win;

        //    Dictionary<string, int> cur_scores = new Dictionary<string, int>
        //    {
        //        { "blue_attack", blue_attack },
        //        { "blue_occupy", blue_occupy },
        //        { "blue_remain", blue_remain },
        //        { "blue_remain_max", blue_remain_max },
        //        { "blue_total", blue_total },
        //        { "blue_win", blue_win },
        //        { "red_attack", red_attack },
        //        { "red_occupy", red_occupy },
        //        { "red_remain", red_remain },
        //        { "red_remain_max", red_remain_max },
        //        { "red_total", red_total },
        //        { "red_win", red_win }
        //    };

        //    return cur_scores;
        //}

        ///// <summary>
        ///// 调用算子内的方法，生成ValidActions并汇总
        ///// </summary>
        ///// <param name="operators"></param>
        ///// <param name="cities"></param>
        ///// <param name="map"></param>
        ///// <param name="shootJudgeTables"></param>
        ///// <returns></returns>
        //private Dictionary<string, Dictionary<string, List<Dictionary<string, object>>>> UpDateValidAction(List<IOperator> operators, List<Dictionary<string, object>> cities, Map map, ShootJudgeTables shootJudgeTables)
        //{
        //    Dictionary<string, Dictionary<string, List<Dictionary<string, object>>>> local_valid_actions = new Dictionary<string, Dictionary<string, List<Dictionary<string, object>>>>();
        //    foreach (IOperator opr in operators)
        //    {
        //        opr.UpdateValidActions(new object[] { operators, cities, map, shootJudgeTables });
        //        dynamic dynamic_opr = opr;
        //        local_valid_actions.Add(dynamic_opr.ObjID.ToString(), dynamic_opr.ValidActions);
        //    }
        //    return local_valid_actions;
        //}
        /// <summary>
        /// 去除不合理的动作
        /// </summary>
        /// <param name="actionListString"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private List<Dictionary<string, string>> ValidateAction(List<Dictionary<string, string>> actionListString)
        {
            if (actionListString == null) return new List<Dictionary<string, string>>();
            List<Dictionary<string, string>> validatedAction = new List<Dictionary<string, string>>();
            // 删除对同一个算子的重复动作
            for (int i = 0; i < actionListString.Count; )
            {
                if (!actionListString[i].ContainsKey("ObjID"))
                {
                    actionListString.RemoveAt(i);
                    Trace.TraceError("输入的action有误，没有ObjID数据");
                }
                else
                {
                    for (int j = i + 1; j < actionListString.Count;)
                    {
                        if (!actionListString[j].ContainsKey("ObjID"))
                        {
                            actionListString.RemoveAt(j);
                            Trace.TraceError("输入的action有误，没有ObjID数据");
                        }
                        else if (actionListString[j]["ObjID"] == actionListString[i]["ObjID"])
                        {
                            actionListString.RemoveAt(j);
                            Trace.TraceWarning($"无效指令：对{actionListString[i]["ObjID"]}算子下达了多条动作指令");
                        }
                        else j++;
                    }
                    i++;
                }
            }

            return validatedAction;
        }

        /// <summary>
        /// 根据ID号获取算子
        /// </summary>
        /// <param name="objID"></param>
        /// <returns></returns>
        private Operator GetOprByID(int objID)
        {
            foreach (Operator opr in operators)
            {
                int thisID = opr.GetAttri("ObjID");
                if (thisID == objID)
                {
                    return opr;
                }
            }
            Trace.TraceWarning($"不存在ID为{objID}的算子。");
            return null;
        }

        private Target GetTarByID(int tarID)
        {
            foreach (Target tar in targets)
            {
                int thisID = tar.GetAttri("TarID");
                if (thisID == tarID)
                {
                    return tar;
                }
            }
            Trace.TraceWarning($"不存在ID为{tarID}的目标。");
            return null;
        }
    }
}
